<?php
namespace gnomephp\mvc;

use gnomephp\Configuration,
	gnomephp\Url,
	gnomephp\message\Message;
class View{
	/**
	 * 
	 * Variables assigned to view.
	 * @var array
	 */
	protected $variables=array();

	
	protected $viewname;
	
	/**
	 * 
	 * Instance of Url helper.
	 * @var gnomephp\Url
	 */
	public $url;
	
	
	/**
	 * Holds the input class.
	 * @var gnomephp\input\Input
	 */
	protected $input;	
	
	
	/**
	 * Holds the input class.
	 * @var gnomephp\helper\lang\Lang
	 */
	protected $lang;
	
	/**
	 * Holds the input class.
	 * @var gnomephp\Session
	 */
	protected $session;
	
	
	/**
	 * This will contain the view name the current view is extending.
	 * If extend() method is used $extendingView is set.
	 * @var string
	 */
	protected $extendingView = null;
	protected $extendingViewAlias = null;
	protected $extendingVars = array();
	
	/**
	 * This will contain the implementation map if there are some view outputs
	 * that is currently implementing this specific view.
	 * @var array
	 */
	protected $implementsMap = array();
	
	
	/**
	 * Constructs the view.
	 * 
	 * @param unknown_type $input
	 * @param unknown_type $lang
	 * @param unknown_type $session
	 */
	public function __construct($input=null, $lang=null, $session=null){
		$this->url = new Url;
		$this->input = $input;
		$this->lang = $lang;
		$this->session = $session;
	}

	
	public function addImplementation($alias, $content){
		$this->implementsMap[$alias] = $content;
	}
	
	public function getExtend($alias){
		if (isset($this->implementsMap[$alias])){
			return $this->implementsMap[$alias];
		}else{
			return null;
		}
	}
	
	
	/**
	 * 
	 * Assigns a variable to the view.
	 * @param string $var Variable name
	 * @param mixed $value Value of the variable, can be array, object, string boolean, etc... all types of variables is accepted.
	 */
	public function assign($var, $value){
		$this->variables[$var] = $value;
	}
	
	
	/**
	 * Sends a specific view to the output.
	 * 
	 * @param string $viewName The view name, Can be in folder too, like template/header, . This will load view/template/header.php
	 * @param boolean $returnContent If you want to return the rendered output instead of echoing it out, you may set this to true.
	 * @param string $suffix The file extension of the view file. Default is .php.
	 */
	public function render($viewName, $returnContent=false, $suffix='.php'){
		
		
		// Assign variables to nice onces... 
		extract($this->variables);
		
		$this->viewname = $viewName;
		$vpath = GNOME_APP_PATH.DIRECTORY_SEPARATOR.'view';
		
		$view = $this;
		
		

		ob_start();
		
		// Include view.
		require $vpath.DIRECTORY_SEPARATOR.$viewName.($suffix ?: $suffix);
	
		$content = ob_get_contents();
		ob_end_clean();
		if ($this->extendingView !== null){
			$v = new View($this->input, $this->lang, $this->session);
			$v->addImplementation($this->extendingViewAlias, $content);
			foreach($this->extendingVars as $k => $va){
				$v->assign($k, $va);
			}
			return $v->render($this->extendingView, $returnContent, $suffix);
		}
			
		if ($returnContent){
			return $content;
		}else{
			echo $content;
		}
		
		
				
	}
	
	/**
	 * 
	 * Imports a view and creates a separate view for the specific view. Useful to use inside templates like:
	 * <? $view->import('header'); ?>
	 * 
	 * @param string $view The view name, Can be in folder too, like template/header, . This will load view/template/header.php
	 * @param array $vars Array of variables to assign to this specific view. Key should be the variable name, Value can be anything.
	 * @param string $suffix The file extension of the view file. Default is .php.
	 */
	public function import($view, $vars=array(), $returnContent=false,  $suffix='.php'){
		$v = new View($this->input, $this->lang, $this->session);
		foreach($vars as $k => $va){
			$v->assign($k, $va);
		}
		$v->render($view, $returnContent, $suffix);
	}
	
	public function extend($view, $alias=false, $vars=array()){
		$this->extendingView = $view;
		$this->extendingViewAlias = $alias ? $alias : $view;
		$this->extendingVars = $vars;
	}
	
	
	
	public function getRuntime(){
		return \gnomephp\mvc\Dispatcher::getRuntime();
	}
	
	
	/**
	 * 
	 * Gets a configuration value from a specific configuration file.
	 * 
	 * @param string $file The configuration file inside the config folder. NOTICE! Do not include .yml extension, this will be added automatically.
	 * @param string $key The key to load, if not provided, it will load all configurations in an array in the config file.
	 * @param string $suffix The suffix of the config file. Default is .yml.
	 */
	public function getConfig($file, $key=null, $suffix='.yml'){
		return \gnomephp\Configuration::get($file, $key, $suffix);
	}
	
	/**
	 * Gets message objects.
	 * @return array Array of MessageItem, check for what type of message with instanceof operator.
	 */
	public function getMessages(){
		return Message::getMessages();
	}
	
	
	public function getViewPath(){
		return  GNOME_APP_PATH.DIRECTORY_SEPARATOR.'view'.DIRECTORY_SEPARATOR;
	}
	
	/**
	 * Creates a new form object.
	 * You can create the form in the controller and assign it to a variable.
	 * If you choose to provide a callback closure as listener it should be defined as:
	 * function ($input){
	 * 		// Do something with the input of the form.
	 * }
	 * 
	 * 
	 * @param string $id Unique id for the form. Example: 'contact_form'
	 * @param string $action The action of where to post the variables.
	 * @param string $method The method to use for posting the form, default is 'post'
	 * @param closure $listener A callback function to use if form is posted. This is not obligatory, but it's a good way of checking if this specific form was posted.
	 */
	public function createForm($id, $action, $method='post', $listener=null){
		return new \gnomephp\form\Form($id, $this->url, $action, $method, $listener, $this->input);
	}
	
	
	
}